#ifndef GS_LIBRARY_H
#define GS_LIBRARY_H

#include "../include/Gs.h"
#include "Managed.h"
#include "KeyValuePair.h"

namespace Gs
{
	class String;
	class Value;

	// Defines the number of hash buckets.
	const int ObjectHashBuckets = 8;

	// Minimum number of key/values per bucket (grows exponentially).
	const int MinimumBucketSize = 4;

	// Represents a GorillaScript object.
	class Object : public Managed, public IObject
	{
	private:
		// Defines the bucket key/value pair type.
		typedef KeyValuePair<String *, Value> BucketKeyValuePair;

		// Stores the hash buckets.
		BucketKeyValuePair *_buckets[ObjectHashBuckets];

		// Stores the current lengths of each bucket.
		unsigned short _bucketLengths[ObjectHashBuckets];

		// Stores the sizes of each bucket.
		unsigned short _bucketSizes[ObjectHashBuckets];

		// Stores the array part of the object.
		Value *_array;

	public:
		// Initialises a new instance of the Object class.
		Object();

		// Destroys the instance.
		~Object();

		// Assigns a value to a key in the object.
		void SetValue(String *key, const Value &value);

		// Gets a value from a key in the object.
		Value *GetValue(String *key) const;
		
		// Removes the specified field (resolving to nil).
		void RemoveField(IString *name);

		// Sets the specified field to an integer value.
		void SetField(IString *name, int i);

		// Sets the specified field to a float value.
		void SetField(IString *name, float f);

		// Sets the specified field to a string value.
		void SetField(IString *name, IContext *context, const char *s);

		// Sets the specified field to a string value.
		void SetField(IString *name, IString *s);

		// Sets the specified field to an object.
		void SetField(IString *name, IObject *o);

		// Sets the specified field to a native function.
		void SetField(IString *name, NativeFunction f);

		// Sets the specified field to a user pointer.
		void SetField(IString *name, UserPointer ptr);

		// Gets the value at the named key.
		IValue *GetField(IString *name) const;
	};
}

#endif